【Bug】记一次环境变量未注入排查过程

记一次环境变量未注入到uat环境的解决过程。

背景

一个使用Next框架的项目里,通过cross-env NODE_ENV=production DEPLOY_ENV=uat 注入全局变量, 在uat环境和sit环境下网页客户端刷新无法取得这个注入的值

感谢 evan 同学的帮忙

记录排查过程

问题描述

项目的src目录下封装了一个可以跳到自己公司其他站点的函数site,并且跳转地址会区分环境.例如在本站点的uat地址进行操做跳转到另一个站点’abc’,也会跳到对应的环境 ‘https://uat.abc.com'。但是,在uat的地址进行操作发现跳到'abc'网站的dev地址, 于是开始进行排查

site的大致定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import { getPrePath } from './index'
const env = process.env.DEPLOY_ENV || 'prd'

export default function outerUrl (name) {
const prePath = getPrePath()
const urls = {
dev: {
abc: 'https://dev.abc.com' + prePath,
def: 'https://dev.def.com' + prePath,
},
sit: {
abc: 'https://sit.abc.com' + prePath,
def: 'https://sit.def.com' + prePath,
},
uat: {
abc: 'https://uat.abc.com' + prePath,
def: 'https://uat.def.com' + prePath,
},
prd: {
abc: 'https://prd.abc.com' + prePath,
prd: 'https://prd.def.com' + prePath,
},
}
}

1 首先去检查 site 的 uat地址是否配错

经检查, uat地址配置正确

2 然后在当前文件打印env

1
2
const env = process.env.DEPLOY_ENV || 'prd'
console.log('env---------------', env)

在本地打印env, 结果是dev。这是没错的,就无法看出问题所在,于是把代码发到uat环境,访问uat地址查看打印效果。

结果uat环境也打印出的是dev。

那说明可能是哪个地方配置错了

3 排查配置文件package.json 的script脚本

1
2
3
4
5
6
7
8
9
{
"scripts" : {
"start": "cross-env NODE_ENV=development DEPLOY_ENV=dev nodemon server/index.js",
"build": "next build",
"prod": "cross-env NODE_ENV=production DEPLOY_ENV=sit node server/index.js",
"sit": "cross-env NODE_ENV=production DEPLOY_ENV=sit && next build && export DEPLOY_ENV=sit gulp",
"uat": "export NODE_ENV=production DEPLOY_ENV=uat && next build && export DEPLOY_ENV=uat gulp",
}
}

执行npm start, 其是是可以拿到 process.env.DEPLOY_ENV的值的

那么,需要在本地模拟出sit环境的构建过程,也就是执行 npm run buildnpm run prod, 执行这里发现打印出的还是dev

搜代码中所有可能出现dev的地方,然后将其改成其他字符, 在本地执行构建命令,发现改了好几个地方,构建的打印还是dev。

直到 改了 next.config.js 文件里面的一个dev改成’dev23’, 执行sit构建 npm run buildnpm run prod,打印中终于发生了变化, 是’dev23’

1
2
3
env: {
DEPLOY_ENV: process.env.DEPLOY_ENV || 'dev23'
},

到此,初步定位出问题所在。
Next框架的配置文件next.config.js无法获取到注入的全局变量。

4 需要查一下next文档

next build 以及 next.config.js 都做了什么 ?

next.config.js可以进行许多打包构建等的配置,next build会执行并生成构建好的文件输出到你配置的路径下面。
其中next.config.js 的 env 可以给客户端注入全局变量, site函数拿到的正是这个全局变量的默认值。为什么这里process.env.DEPLOY_ENV没有成功赋值呢, 又要回到注入这个全局变量的地方看一下
发现上一步 "build": "next build", 执行build时根本没有注入变量,于是修改配置文件为

1
2
3
4
5
6
7
{
"scripts" : {
"start": "cross-env NODE_ENV=development DEPLOY_ENV=dev nodemon server/index.js",
"build": "cross-env NODE_ENV=production DEPLOY_ENV=sit && next build", // 主要是这里修改
"prod": "cross-env NODE_ENV=production DEPLOY_ENV=sit node server/index.js",
}
}

再次执行npm run buildnpm run prod模拟sit环境,next.config.js 文件打印的process.env.DEPLOY_ENV是undefined,也就是说这个环境变量还是没有注入

5 google【关键词】(next cross-env process.env.DEPLOY_ENV undeifined)

搜索问题关键词, 这是很重要的一步。

在这个网页中看到了一些类似的问题
https://stackoverflow.com/questions/11104028/process-env-node-env-is-undefined/38948727

in package.json we have to config like below (works in Linux and Mac OS)
the important thing is “export NODE_ENV=production” after your build commands below is an example:

1
2
3
4
5
6
7
"scripts": {  
"start": "export NODE_ENV=production && npm run build && npm run start-server",
"dev": "export NODE_ENV=dev && npm run build && npm run start-server",

//
"start": "cross-env NODE_ENV=dev node your-app-name.js"
}

这里面提到不同的注入变量的方法: set 、cross-env 、export
发现如果后面跟的是构建命令, 则用export来注入, 如果是node index.js等文件就直接用cross-env注入

按照这样的思路尝试改一下sit 和 uat注入变量的方式,

1
2
3
4
5
6
7
{
"scripts" : {
"start": "cross-env NODE_ENV=development DEPLOY_ENV=dev nodemon server/index.js",
"sit": "export NODE_ENV=production DEPLOY_ENV=sit && next build && export DEPLOY_ENV=sit gulp",
"uat": "export NODE_ENV=production DEPLOY_ENV=uat && next build && export DEPLOY_ENV=uat gulp",
}
}

再次测试果然,可以正确的拿到对应的环境变量了,进行发布,也成功拿到环境变量了

后续

后来,Jade 讲到他对我们项目的脚手架进行了更新,可以使用cross-env正常拿到环境变量了。
cross-env 后面只能定义一个环境变量
NODE_ENV=production 已经在next框架默认设置了,无需额外注入
这样试了一下,也可以拿到环境变量了

1
2
3
4
5
6
{
"scripts" : {
"build": "node task/index.js && next build",
"sit": "cross-env DEPLOY_ENV=sit npm run build && cross-env DEPLOY_ENV=sit gulp",
}
}

思考

这次找环境配置问题, 发现自己还是对运行环境、部署环境、服务端的知识有很大的欠缺。
但是get到了更好的解决问题的方式, 顺藤摸瓜,本地模拟测试环境、搜索关键词、查文档等,还有细心

-------------本文结束 感谢您的阅读-------------
请我吃辣条吖~